<?php
/**
 * This file is part of easycrm, created by PhpStorm.
 * Author: LouXin
 * Date: 2015/2/16 13:23
 * File: RerunCommand.php
 */

namespace Icsoc\ReportBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;

class RerunCommand extends ContainerAwareCommand
{
    const REGEX_DATE = '/\d\d\d\d-\d\d-\d\d/';
    const SHELL_COMMAND = 'ps aux|grep "report:rerun"';

    protected function configure()
    {
        $this
            ->setName('report:rerun')
            ->setDescription('重新整理指定日期的报表')
            ->addOption('startDate', 'sd', InputOption::VALUE_REQUIRED, '报表的开始日期，格式为2015-01-01')
            ->addOption('endDate', 'ed', InputOption::VALUE_OPTIONAL, '报表的结束日期，格式为2015-01-01，空代表当天')
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $startDate = $input->getOption('startDate');
        $endDate = $input->getOption('endDate');
        $env = $input->getOption('env');
        $endDate = empty($endDate) ? date('Y-m-d') : $endDate;

        try {
            $startDate = new \DateTime($startDate);
        } catch (\Exception $e) {
            $output->writeln(sprintf('开始日期 [%s] 格式不正确', $startDate));

            return 255;
        }
        try {
            $endDate = new \DateTime($endDate);
        } catch (\Exception $e) {
            $output->writeln(sprintf('结束日期 [%s] 格式不正确', $endDate));

            return 255;
        }

        $interval = $startDate->diff($endDate);
        $formatInterval = $interval->format('%r%a');
        if ($formatInterval < 0) {
            $output->writeln(sprintf(
                '结束日期 [%s] 小于开始日期 [%s]',
                $endDate->format('Y-m-d'),
                $startDate->format('Y-m-d')
            ));

            return 255;
        }
        if ($formatInterval > 7) {
            $output->writeln(sprintf(
                '结束日期 [%s] 与开始日期 [%s] 相差 [%s] 天，不能超过7天',
                $endDate->format('Y-m-d'),
                $startDate->format('Y-m-d'),
                $formatInterval
            ));

            return 255;
        }

        //检查报表服务进程是否在运行
        @exec(self::SHELL_COMMAND, $result);
        $count = isset($result[0]) ? count($result) : 0;
        if ($count > 4) {
            //进程正在执行
            $output->writeln(sprintf('[%s] 报表重跑服务进程正在执行，无法执行该命令，结果为【%s】.', date('Y-m-d H:i:s'), var_export($result, true)));

            return 1;
        }

        ini_set('memory_limit', '2048M');
        $logDir = $this->getContainer()->get('kernel')->getLogDir();
        for ($date = $startDate; $startDate <= $endDate; $startDate->add(new \DateInterval('P1D'))) {
            //删除统计表中的数据
            $output->writeln(sprintf('开始删除数据库中统计表中日期 [%s] 的数据', $date->format('Y-m-d')));
            if (!$this->deleteDatabaseData($date->format('Y-m-d'))) {
                $output->writeln(sprintf('删除数据库中统计表中日期 [%s] 的数据失败', $date->format('Y-m-d')));

                return 2;
            }
            $output->writeln(sprintf('删除数据库中统计表中日期 [%s] 的数据成功', $date->format('Y-m-d')));

            $tmpTimeLogFile = $logDir . '/'.$env.'.report_time-' . $date->format('Y-m-d') . '.log';
            if (!file_exists($tmpTimeLogFile)) {
                $output->writeln(sprintf('时长日志文件 [%s] 不存在,请检查报表整理程序计划任务中设置的环境 dev OR prod', $tmpTimeLogFile));

                return 255;
            }
            $output->writeln(sprintf('开始处理时长日志文件 [%s] ...', $tmpTimeLogFile));
            $conn = $this->getContainer()->get('doctrine.dbal.default_connection');
            $contents = file($tmpTimeLogFile);
            foreach ($contents as $line => $row) {
                $row = substr($row, 45);
                $row = substr($row, 0, -7);
                $row = str_replace("\r\n", "", $row);
                $row = explode(',', $row);
                $rowData = array(
                    'id' => $row[0],
                    'vcc_id' => $row[1],
                    'call_id' => $row[2],
                    'que_id' => $row[3],
                    'ag_id' => $row[4],
                    'group_id' => $row[5],
                    'type' => $row[6],
                    'ext_type' => $row[7],
                    'starttime' => strtotime($row[8]),
                    'endtime' => strtotime($row[10]),
                    'call_time' => strtotime($row[11]),
                    'ext_option' => $row[12],
                );
                $conn->insert('rep_tmp_time', $rowData);
                unset($rowData);
                unset($contents[$line]);
            }
            $output->writeln(sprintf('处理时长日志文件 [%s] 成功', $tmpTimeLogFile));

            $tmpAmountLogFile = $logDir . '/'.$env.'.report_amount-' . $date->format('Y-m-d') . '.log';
            if (!file_exists($tmpTimeLogFile)) {
                $output->writeln(sprintf('量日志文件 [%s] 不存在,请检查报表整理程序计划任务中设置的环境 dev OR prod', $tmpAmountLogFile));

                return 255;
            }
            $output->writeln(sprintf('开始处理量日志文件 [%s] ...', $tmpAmountLogFile));
            $contents = file($tmpAmountLogFile);
            foreach ($contents as $line => $row) {
                $row = substr($row, 47);
                $row = substr($row, 0, -7);
                $row = str_replace("\r\n", "", $row);
                $row = explode(',', $row);
                $rowData = array(
                    'id' => $row[0],
                    'vcc_id' => $row[1],
                    'que_id' => $row[2],
                    'ag_id' => $row[3],
                    'group_id' => $row[4],
                    'type' => $row[5],
                    'starttime' => strtotime($row[6]),
                    'call_time' => strtotime($row[7]),
                );
                $conn->insert('rep_tmp_amount', $rowData);
                unset($rowData);
                unset($contents[$line]);
            }
            $output->writeln(sprintf('处理量日志文件 [%s] 成功', $tmpAmountLogFile));
            $conn->close();
        }

        return 0;
    }

    /**
     * 删除数据库中指定日期的数据
     *
     * @param string $date 日期
     *
     * @return bool
     */
    protected function deleteDatabaseData($date)
    {
        if (empty($date)) {
            return false;
        }

        $conn = $this->getContainer()->get('doctrine.dbal.default_connection');
        $conn->beginTransaction();
        try {
            $conn->delete('rep_agent_day', array('nowdate' => $date));
            $conn->delete('rep_agent_halfhour', array('start_date' => $date));
            $conn->delete('rep_agent_hour', array('start_date' => $date));
            $conn->delete('rep_queue_day', array('nowdate' => $date));
            $conn->delete('rep_queue_halfhour', array('start_date' => $date));
            $conn->delete('rep_queue_hour', array('start_date' => $date));
            $conn->delete('rep_system_day', array('nowdate' => $date));
            $conn->delete('rep_system_halfhour', array('start_date' => $date));
            $conn->delete('rep_system_hour', array('start_date' => $date));

            $conn->commit();
            $conn->close();

            return true;
        } catch (\Exception $e) {
            $conn->rollBack();
            $conn->close();

            return false;
        }
    }
}
